﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using System.Threading;

namespace Gsp315_AIBehaviors
{
    public static class Helper
    {
        #region COMMON_DEGs_2_RADIANs_CONVERSION
        //
        //30 degrees on Radians
        public const float InRADIANs_30_DEG = (float)Math.PI / 6;
        //45 degrees on Radians
        public const float InRADIANs_45_DEG = (float)Math.PI / 4;
        //60 degrees on Radians
        public const float InRADIANs_60_DEG = (float)Math.PI * (2 / 3);
        //90 degrees on Radians
        public const float InRADIANs_90_DEG = (float)Math.PI / 2;
        //270 degrees on Radians
        public const float InRADIANs_270_DEG = (float)Math.PI * (3 / 2);
        //
        #endregion COMMON COMMON_DEGs_2_RADIANs_CONVERSION


        private static Random rand = new Random();

        //-------------------------------------------------------------------------
        //M001: Convert Angle: Degrees->Radians
        public static float Degree2Radian(float angleDeg)
        {
            //float rad = (float)Math.Round(angleDeg * (Math.PI / 180), 2);
            //return rad;
            return (float)Math.Round(angleDeg * (Math.PI / 180), 2 );
        }


        //-------------------------------------------------------------------------
        //M002: Convert Angle: Radians->Degrees
        public static float Radian2Degree(float angleRad)
        {
            //float rad = (float)Math.Round(angleDeg * (180 / Math.PI), 2);
            //return rad;
            return (float)Math.Round(angleRad * (180 / Math.PI), 2);
        }


        //-------------------------------------------------------------------------
        //M003: Convert Radians->Vector2
        public static Vector2 Radian2Vector(float angleRad)
        {
            Vector2 temp = new Vector2();

            //theta is 360 or Zero  degrees...
            if (angleRad == (float)Math.Round((float)Math.PI * 2, 2) || angleRad == 0.0f)
            {
                temp.X = 1.0f; temp.Y = 0.0f;
            }
            //theta is 90 degrees...
            else if (angleRad == (float)Math.Round(MathHelper.PiOver2, 2))
            {
                temp.X = 0.0f; temp.Y = 1.0f;
            }
            //theta is 180 degrees...
            else if (angleRad == (float)Math.Round((float)Math.PI, 2))
            {
                temp.X = -1.0f; temp.Y = 0.0f;
            }
            //theta is 270 degrees...
            else if (angleRad == (float)Math.Round(InRADIANs_270_DEG, 2))
            {
                temp.X = 0.0f; temp.Y = -1.0f;
            }
            else
            {
                temp.X = (float)Math.Round(Math.Cos(angleRad), 2);
                temp.Y = (float)Math.Round(Math.Sin(angleRad), 2);
            }

            return temp;
        }


        //-------------------------------------------------------------------------
        //M004: Generate a random theta, in RADIANS obj should move in
        //Use this method if single obj need angle, in ONE frame
        public static float AngleInRadians_Random()
        {
            Random rand = new Random(); //random seed, provided...
            int minTheta = 0; int maxTheta = 359;

            //Random angle between Zero|360 in DEGREES
            float angle = (float)Math.Round(((rand.NextDouble() * (maxTheta - minTheta)) + minTheta), 2);

            //putting the thread to sleep will make sure a NEW random seed is called each time....
            Thread.Sleep(8);

            return Degree2Radian(angle);
        }


        //-------------------------------------------------------------------------
        //M005: Generate a random theta, in RADIANS obj should move in
        //Use this method if multiple objs need random angle, in ONE frame
        public static float AngleInRadians_Random(Random rand)
        {
            int minTheta = 0; int maxTheta = 359;

            //Random angle between Zero|360 in DEGREES
            float angle = (float)Math.Round(((rand.NextDouble() * (maxTheta - minTheta)) + minTheta), 2);

            return Degree2Radian(angle);
        }


        //-------------------------------------------------------------------------
        //M006: Generate a random vector2 based on given min|max range
        //Use this method for single obj position, in ONE frame
        public static Vector2 Position_Random(int minX, int maxX, int minY, int maxY)
        {
            //Random rand = new Random(); //new Random((int)DateTime.Now.Ticks); //random seed...

            //X-Value: Generate a random 'float 2-decimal places' between a min|max range
            float x = (float)Math.Round( ( (rand.NextDouble() * (maxX - minX) ) + minX ), 2);
            //Y-Value: Generate a random 'float 2-decimal places' between a min|max range
            float y = (float)Math.Round( ( (rand.NextDouble() * (maxY - minY) ) + minY ), 2);

            return new Vector2(x, y);
         }


        //-------------------------------------------------------------------------
        //M007: Generate a random vector2 based on given min|max range
        //Use this method if multiple objs need random position, in ONE frame
        public static Vector2 Position_Random(Random xPosSeed, Random yPosSeed, int minX, int maxX, int minY, int maxY)
        {
            //X-Value: Generate a random 'float 2-decimal places' between a min|max range
            float x = (float)Math.Round(((xPosSeed.NextDouble() * (maxX - minX)) + minX), 2);
            //Y-Value: Generate a random 'float 2-decimal places' between a min|max range
            float y = (float)Math.Round(((yPosSeed.NextDouble() * (maxY - minY)) + minY), 2);

            //putting the thread to sleep will make sure a random seed to get called....
            Thread.Sleep(5);

            return (new Vector2(x, y));
        }


        //-------------------------------------------------------------------------
        //M008: Generate a random number  between and including given min|max range
        //Use this method if single obj needs random clamp, in ONE frame
        public static float RandomClamp(int min, int max)
        {
            Random rand = new Random();
            float randClamp = 0.0f;

            randClamp = (float)Math.Round(((rand.NextDouble() * (max - min)) + min), 2);

            Thread.Sleep(8);

            return (randClamp);
        }


        //-------------------------------------------------------------------------
        //M009: Generate a random number  between and including given min|max range
        //Use this method if multiple objs need random clamp, in ONE frame
        public static float RandomClamp(Random rand, int min, int max)
        {
            float randClamp = 0.0f;

            randClamp = (float)Math.Round(((rand.NextDouble() * (max - min)) + min), 2);

            return (randClamp);
        }


        //-------------------------------------------------------------------------
        //M010: Generate a random number  between and including given min|max range
        //Use this method if multiple objs need random clamp, in ONE frame
        public static float RandomClamp(Random rand, float min, float max)
        {
            float randClamp = 0.0f;

            randClamp = (float)Math.Round(((rand.NextDouble() * (max - min)) + min), 2);

            return (randClamp);
        }


        //-------------------------------------------------------------------------
        //M011 Return an Inversed Vector2 
        public static Vector2 Inverse(Vector2 value)
        {
            Vector2 temp = new Vector2(-1, -1);
            return (temp * value);
        }
    }//class
}//namespace
